use super::mbox::{MBox};
use super::meta::{Meta};
use super::mmap::Mmap;
use super::memregion::MemoryRegion;
use super::head::{head,AHead,Headed};

use std::fmt;
use std::io::{Result};
use std::fs::OpenOptions;
use std::path::Path;

#[derive(Debug)]
pub struct CPBlock<T> where T:Headed {
    pub fname : String,
    pub head : MBox<AHead<T>>,
    pub meta : Meta,
    pub data : Option<MemoryRegion>,
    meta_h : Mmap,
}

impl<T:Headed> fmt::Display for CPBlock<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{} {}",self.fname,*AHead::<T>::as_head(&self.head).unwrap())
    }
}

impl<T:Headed> CPBlock<T> {
    pub fn attach(fname: String) -> Result<Self> {
        let p = Path::new(&fname);
        let h = head::read_head(p)?;
        let ms = h.meta_size as usize;
        let f = OpenOptions::new().read(true).write(true).open(p)?;
        let m = Mmap::map_mut(ms,&f,0_u64)?;
        let meta = Meta::init(m.to_raw());
        let head = meta.attach::<AHead<T>>(0 as usize)?;
        let mr = MemoryRegion::new(fname.clone())?;
        Ok(CPBlock{
            fname:fname,
            head:head,
            meta:meta,
            data:mr,
            meta_h:m,
        })
    }
}

